package com.nercel.dsj.gksales.util.sms.unicom;

import java.io.IOException;
import java.io.Serializable;
import java.time.Instant;

import org.springframework.util.DigestUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import lombok.extern.slf4j.Slf4j;

/**
 * 短信平台发送短信时请求的字段
 * 
 * @author qsx (变量名大写开头我也没办法)
 * @date 2020-09-04 13:12:13
 */
@Slf4j
public class MessageRequest implements Serializable {
    /**
    *
    */
    private static final long serialVersionUID = 898652735387669427L;

    /**
     * 登录名称 (非用户登录平台账号，由管理员提供)
     */
    private String LoginName;
    /**
     * 短信模板ID
     */
    private String SmsTempletID;
    /**
     * 短信模板参数JSON串，例如： {'test':'1023','ceshi':'abc'} （多个参数值后“,”分隔)
     */
    private String parameter;
    /**
     * 接收用户号码，仅限一个接收该短消息的手机号手机号码前加“86”国别标志，如8613001125453
     */
    private String UserNumber;
    /**
     * 时间戳，单位毫秒
     */
    private String Timestamp;

    private transient String spPassword;
    /**
     * <p>
     * <li>1. 使用分配的spPassword为Key进行MD5加密，字符集使用GBK</li>
     * <li>2.
     * 请求串各字段以参数名首字母为序（A-Z）排列，参数名参数值以=连接，不同参数以&连接,并将spPassword即key值加在验签原串末尾（如下例验签原串）。</li>
     * <li>3. 参数值含特殊符号时不需进行URLEncode</li>
     * <li>4. Verify参数本身不参与验签</li>
     * <li>5. 生成MD5验签串，字母为大写</li>
     * </p>
     * <p>
     * 示例： </br>
     * LoginName:wwjytd</br>
     * Parameter:{‘test’,‘1023’}</br>
     * SmsTempletID:151217175525788001</br>
     * Timestamp:1557051460707</br>
     * UserNumber:8613001125453</br>
     * spPassword:123456</br>
     * 【验签原串】LoginName=wwjytd&Parameter={'test':'1023','ceshi':'abc'}&SmsTempletID=151217175525788001&Timestamp=1557052614689&UserNumber=8613001125453123456
     * 生成的验签串：CA4CCE18A3100EF941BE70AEC2AFF101
     * </p>
     */

    private String Verify;

    public String getLoginName() {
	return LoginName;
    }

    public void setLoginName(String loginName) {
	LoginName = loginName;
    }

    public String getSmsTempletID() {
	return SmsTempletID;
    }

    public void setSmsTempletID(String smsTempletID) {
	SmsTempletID = smsTempletID;
    }

    public String getParameter() {
	return parameter;
    }

    public void setParameter(String parameter) {
	this.parameter = parameter;
    }

    public String getUserNumber() {
	return UserNumber;
    }

    /**
     * 手机号默认在前端加上86
     */
    public void setUserNumber(String userNumber) {
	UserNumber = "86" + userNumber;
    }

    public String getVerify() {
	return Verify;
    }

    public void setVerify(String verify) {
	Verify = verify;
    }

    /**
     * 设计时间戳为当前时间
     */
    public void setTimestamp(boolean isCurrent, String Timestamp) {
	if (isCurrent) {
	    this.Timestamp = Instant.now().toEpochMilli() + "";
	} else {
	    this.Timestamp = Timestamp;
	}
    }

    public String getTimestamp() {
	return Timestamp;
    }

    public String getSpPassword() {
	return spPassword;
    }

    public void setSpPassword(String spPassword) {
	this.spPassword = spPassword;
    }

    /**
     * 将本对象转成Json字符串
     */
    public String toJsonString() {
	Gson gson = new GsonBuilder().disableHtmlEscaping() // 忽略Html标签，如:“<”、“>”、“'”等
		.registerTypeAdapter(this.getClass(), new MessageRequestAdapter()).create(); // 按指定顺序输出Json
	log.info("转成json的结果：" + gson.toJson(this));
	return gson.toJson(this);
    }

    /**
     * 取字符串MD5值
     */
    public String md5HexUpperCase() {
	String upperCase = DigestUtils.md5DigestAsHex(addVerify(reformData(toJsonString())).getBytes()).toUpperCase();
	log.info("MD5加密后的结果：" + upperCase);
	return upperCase;
    }

    /**
     * 取字符串MD5值
     */
    public String md5HexUpperCase(String data) {
	String upperCase = DigestUtils.md5DigestAsHex(data.getBytes());
	log.info("MD5加密后的结果：" + upperCase);
	return upperCase;
    }

    /**
     * 满足短信平台验签的要求处理字符串，将“"”和“{”、“}”都去掉
     * <p>
     * ag：将{"a":"a","b":"b"}处理成a=a&b=b
     * </p>
     */
    private String reformData(String data) {
	String replace = data.substring(2, data.length() - 1) // 去掉头部的{"和尾部的"}
		.replace("\",\"", "&") // 将","替换成&
		.replace("\":\"", "="); // 将":"替换成=
	log.info("替换的结果：" + replace);
	return replace;
    }

    /**
     * 满足短信平台验签的要求,将Verify字段加到尾部
     */
    private String addVerify(String source) {
	return source + this.Verify;
    }

    public class MessageRequestAdapter extends TypeAdapter<MessageRequest> {

	@Override
	public void write(JsonWriter out, MessageRequest value) throws IOException {
	    out.beginObject();
	    // 按指定顺序输出Json
	    out.name("LoginName").value(value.LoginName);
	    out.name("Parameter").value(value.parameter);
	    out.name("SmsTempletID").value(value.SmsTempletID);
	    out.name("Timestamp").value(value.Timestamp);
	    out.name("UserNumber").value(value.UserNumber);
	}

	@Override
	public MessageRequest read(JsonReader in) throws IOException {
	    return null;
	}
    }

    public static void main(String[] args) {
	MessageRequest mr = new MessageRequest();
	mr.setLoginName("10273");
	mr.setSmsTempletID("1027302009041058091011513");
	mr.setParameter(Parameter.toJsonString("code", "666666"));
	mr.setTimestamp(true, null);
	mr.setUserNumber("15271863915");
	mr.setVerify("B219FA943EC175C7C797CB39529B6C15");
	mr.setSpPassword("yqzh10273");
	String json = mr.toJsonString();
	String reformData = mr.reformData(json);
	String addVerify = mr.addVerify(reformData);
	String hexUpperCase = mr.md5HexUpperCase(
		"LoginName=10273&Parameter={'code':'666666'}&SmsTempletID=1027302009041058091011513&Timestamp=1557052614689&UserNumber=8615271863915yqzh10273");
	mr.md5HexUpperCase(addVerify);
	log.info(hexUpperCase);
    }

}
